////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBot\WordSet.h
///
/// @brief  Defines the CollabRC::Bot::WordSet interface
////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <QtCore/QString>
#include "exceptions.h"

namespace CollabRC
{
    namespace Bot
    {
        /**
         * @brief Abstract representation of a set of words with the counts
         * for each word.        
         *
         * A WordSet is an implementation of an iterator which has an internal
         * pointer to a "current word". This current word can be operated on,
         * or the user can move to the next word in the iteration. Alternatively,
         * the iteration can be reset back to the first word. There is no guarantee
         * that successive iterations will follow the same order.
         *
         * The initial position of this iterator, or the position after any reset,
         * is a pseudo-element called "start" from which it is invalid to query data. 
         * The only valid operation from this position is to move to the next element.
         * Additionally, another pseudo-element called "end" exists which is pointed to
         * when all words have been enumerated, signaled by a call to NextWord()
         * returning \c false. The only valid operation at this point is to reset the
         * iterator. The pseudo-elements "start" and "end" may be the same position.
         * If and only if this is the case, then there are no words in the set.
         * @version $Id$
         * @author Matthew P. Del Buono
         */
        class WordSet
        {
        public:
            /**
             * @brief Destroys this WordSet and all associated resources
             */
            inline virtual ~WordSet(void) { };

            /**
             * @brief Gets the current word pointed to by this iterator
             * @return a reference to the current word
             * @throws NoCurrentElementException if the iterator
             * has gone beyond the end of the set already and has not since
             * been reset or if the iterator is currently at the pseudo-element
             * "start"
             */
            virtual const QString& GetCurrentWord() const = 0;

            /**
             * @brief Gets the total occurrences of the word currently
             * pointed to by this iterator.
             * @return the total number of occurrences of the current word 
             * @throws NoCurrentElementException if the iterator
             * has gone beyond the end of the set already and has not since
             * been reset
             */
            virtual unsigned int GetCurrentWordCount() const = 0;

            /**
             * @brief Moves to the next word in the set.
             * 
             * A future call to GetCurrentWord() or GetCurrentWordCount()
             * will reflect the newly encountered word. If there are no
             * more words in the iterator, this is signalled by a return value
             * of \c false and the iterator is positioned at the pseudo-element
             * "end".
             * @return \c true if the operation was successful, or \c false
             * if there are no more words in the set
             */
            virtual bool NextWord() const = 0;

            /**
             * @brief Resets the set back to the start of the list.
             *
             * This positions the iterator at the pseudo-element "start"
             * where calls to GetCurrentWord() or GetCurrentWordCount() will
             * fail. To move the iterator to the first word, make a call
             * to NextWord().
             */
            virtual void Reset() const = 0;
        };
    }
}